﻿package bdz.common.model
{
	import bdz.common.events.XMLLoaderEvent;
	import bdz.common.utils.UploadPostHelper;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;
	/**
	 * The XMLHTTP class wraps the URLLoader class to be used when communicating 
	 * and loading XML Object through HTTP Stream.
	 * 
	 */
	public class XMLLoader extends EventDispatcher
	{
		private var compressed:Boolean;
		protected var httpconnection:URLLoader;
		protected var eventType:String;
		protected var request:URLRequest;
		protected var helper:UploadPostHelper;
		
		public function XMLLoader(_event:String = null){
			if(_event){
				eventType = _event;	
			}
			initializeConnection();
		}
		private function initializeConnection():void{
			httpconnection = new URLLoader();
			request = new URLRequest();
			request.method = "POST";
			httpconnection.dataFormat = "xml";
			httpconnection.addEventListener(IOErrorEvent.IO_ERROR, iofaultHandler);
			httpconnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, faultHandler);
			httpconnection.addEventListener(Event.COMPLETE, resultHandler);
			httpconnection.addEventListener(Event.OPEN, invokeHandler);
			httpconnection.addEventListener(ProgressEvent.PROGRESS, progressHandler);
		}
		protected function progressHandler(event:ProgressEvent):void{
			var total:Number = Math.ceil(event.bytesLoaded/event.bytesTotal)*100;
			dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.PROGRESS, {percent:total, loaded:event.bytesLoaded, total:event.bytesTotal}));
		}
		protected function iofaultHandler(event:IOErrorEvent):void{
			dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.IOFAULT, event));
		}

		protected function faultHandler(event:SecurityErrorEvent):void{
			dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.FAULT, event));
		}
		protected function resultHandler(event:Event):void {
			
			if (compressed) {
				
				var outdata:ByteArray = httpconnection.data;
				try{
					outdata.uncompress();
				}catch(e:Error){
					trace("ERROR DECOMPRESSING :  " + httpconnection.data + " CODE : " + e.message);
					dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.FAULT, event));
					return;
				}
				compressed = false;
			}
			if(eventType){
				dispatchEvent(new XMLLoaderEvent(eventType, compressed ? outdata : httpconnection.data));
			}else{
				dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.RESULT, compressed ? outdata : httpconnection.data));
			}
		}
		protected function invokeHandler(event:Event):void{
			dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.INVOKE, event));
		}
		/**
		* This method is used to invoke the external service. 
		* 
		* 
		* @param param1 Optional. The object to be passed on the external service being invoked.
		* @param param2 Describe param2 here.
		* 
		* @return Nothing
		*
		*
		* 
		*/
		public function sendPostHelp(params:Object, filename:String=null, file:ByteArray = null, compressreturn:Boolean = false):void{
			compressed = compressreturn;
			httpconnection.dataFormat = URLLoaderDataFormat.BINARY;
			request.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
			request.method = URLRequestMethod.POST;
			request.data = UploadPostHelper.getPostData(filename, file, params);
			request.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
			httpconnection.load(request);
			
		}
		public function sendCompressed(obj:* = null):void {
			compressed = true;
			var bdata:ByteArray = new ByteArray();
			if(obj is XML){
				obj = (obj as XML).toXMLString();
			}
			
			if(obj){			
				bdata.writeUTFBytes(obj);
				bdata.compress();
			}
			
			httpconnection.dataFormat = URLLoaderDataFormat.BINARY;
			send(bdata);
		}
		public function send(obj:* = null, compressreturn:Boolean = false):void{
			try{
				if(compressreturn){
					compressed = true;
					httpconnection.dataFormat = URLLoaderDataFormat.BINARY;
				}
				request.data = obj;
				httpconnection.load(request);
				
			}catch(e:Error){
				throw new Error(e.message);
			}
		}
		/**
		* The property used to set the location or URL/URI of the external service to be invoked.
		* 
		* 
		* 
		* @param param1 Optional. The object to be passed on the external service being invoked.
		* @param param2 Describe param2 here.
		* 
		* @return Nothing
		*
		* 
		*/
		public function set location(_url:String):void{
			request.url = _url;
		}
		public function get location():String{
			return request.url;
		}
		/**
		* The property used to set the method to be used when invoking an external service.
		* 
		* <p> Values can be "POST" or "GET" </p>
		* <b>Note:</b> This does not support "PUT" or "DELETE" used by ruby.
		* 
		*  
		* @return Nothing
		* 
		*/
		public function set method(m:String):void{
			request.method = m;
		}
		public function get method():String{
			return request.method;
		}
		public function set contentType(t:String):void{
			request.contentType = t;
		}
		
	}
}

